
#include "SoundWorld.h"
#include <FL/fl_ask.H>
#include <math.h>
#define SLIDER_THICKNESS 17


SoundWorld::SoundWorld(int x, int y, int w, int h) :
    Fl_Group(x, y, w, h),
    sliderXScroll(x , y +h-SLIDER_THICKNESS, w-SLIDER_THICKNESS-80, SLIDER_THICKNESS),
    sliderYScroll(x + w - SLIDER_THICKNESS, y , SLIDER_THICKNESS, h-SLIDER_THICKNESS-80),
    sliderXZoom(x + w-SLIDER_THICKNESS-80 , y +h-SLIDER_THICKNESS, 80, SLIDER_THICKNESS),
    sliderYZoom(x + w - SLIDER_THICKNESS, y+h-SLIDER_THICKNESS-80 , SLIDER_THICKNESS, 80),
    glWindow(x, y, w-SLIDER_THICKNESS, h-SLIDER_THICKNESS)
{
  //...(you could add dynamically created child widgets here)...
    sliderXScroll.type(FL_HORIZONTAL);
    sliderXZoom.type(FL_HORIZONTAL);
    resizable(glWindow);

    sliderXScroll.bounds(0.0, 128.0);
    sliderXScroll.value(0.0);
    sliderXScroll.callback(xValueChanged_CB, (void*)this);
    sliderYScroll.bounds(128.0, 0.0);
    sliderYScroll.value(0.0);
    sliderYScroll.callback(yValueChanged_CB, (void*)this);
    sliderXZoom.bounds(2.0, 18.0);
    sliderXZoom.value(4.0);
    sliderXZoom.callback(xValueChanged_CB, (void*)this);
    sliderYZoom.bounds(4.0, 128.0);
    sliderYZoom.value(16.0);
    sliderYZoom.callback(yValueChanged_CB, (void*)this);
    setupGlWindowX();
    setupGlWindowY();

    end(); // don't forget to do this!
}


// Someone changed one of the sliders
void SoundWorld::setupGlWindowX()
{
    glWindow.leftCamera = (int)(sliderXScroll.value());// - (sliderXZoom.value() * sliderXZoom.value() ));
    glWindow.rightCamera = (int)(sliderXScroll.value() + (sliderXZoom.value() * sliderXZoom.value() ));
    glWindow.setCamera();
    glWindow.setupGrid();
    glWindow.redraw();
}

// Someone changed one of the sliders
void SoundWorld::setupGlWindowY()
{
    glWindow.bottomCamera = (int)(sliderYScroll.value());
    glWindow.topCamera = (int)(sliderYScroll.value() + sliderYZoom.value());
    glWindow.setCamera();
    glWindow.setupGrid();
    glWindow.redraw();
}

void SoundWorld::xValueChanged_CB(Fl_Widget*, void*userdata)
{
    SoundWorld *appwin = (SoundWorld*)userdata;
    appwin->setupGlWindowX();
}

void SoundWorld::yValueChanged_CB(Fl_Widget*, void*userdata)
{
    SoundWorld *appwin = (SoundWorld*)userdata;
    appwin->setupGlWindowY();
}

int SoundWorld::handle(int event)
{
   switch (event)
   {

        case FL_MOUSEWHEEL:

            double fractionOfTheScreen = (double)Fl::event_x() / (double)glWindow.w();
            double zoomCenter = ((double)glWindow.rightCamera - (double)glWindow.leftCamera)*fractionOfTheScreen + (double)glWindow.leftCamera;
            double leftOfZoomCenter = zoomCenter - (double)glWindow.leftCamera;
            double rightOfZoomCenter = (double)glWindow.rightCamera - zoomCenter;

            double zoom = 1.0 + (double)Fl::event_dy() * 0.4;

            leftOfZoomCenter *= zoom;
            rightOfZoomCenter *= zoom;

            glWindow.leftCamera = zoomCenter - leftOfZoomCenter;
            glWindow.rightCamera = zoomCenter + rightOfZoomCenter;
            glWindow.setupGrid();
            glWindow.redraw();

       /*     glWindow.leftCamera = sliderXScroll.clamp(glWindow.leftCamera);*/
            sliderXScroll.value(glWindow.leftCamera);
           /* if (glWindow.leftCamera > sliderXScroll.maximum())
            {
                glWindow.leftCamera = sliderXScroll.maximum();
                sliderXScroll.value(glWindow.leftCamera);
                setupGlWindow();
            }
            if (glWindow.leftCamera < sliderXScroll.minimum())
            {
                glWindow.leftCamera = sliderXScroll.minimum();
                sliderXScroll.value(glWindow.leftCamera);
                setupGlWindow();
            }*/

            double newValue = sqrt((double)glWindow.rightCamera - (double)glWindow.leftCamera);
            //newValue = sliderXZoom.clamp(newValue);
            sliderXZoom.value(newValue);

          /*  setupGlWindow();*/
        /*    if (newValue > sliderXZoom.maximum())
            {
                newValue = sliderXZoom.maximum();
                sliderXZoom.value(newValue);
                setupGlWindow();
            }
            if (newValue < sliderXZoom.minimum())
            {
                newValue = sliderXZoom.minimum();
                sliderXZoom.value(newValue);
                setupGlWindow();
            }
*/



           /* double newXValue;
            double temp = (double)(Fl::event_x()-w()/2)/(double)w();
            //temp *= temp;
            if (Fl::event_dy() < 0)
                newXValue = (double)sliderXScroll.value() + temp * -(double)Fl::event_dy() * 4.0;
            else
                newXValue = (double)sliderXScroll.value() + temp * (double)Fl::event_dy() * 4.0;
            sliderXScroll.value(newXValue);

            double newValue = sliderXZoom.value() + (double)Fl::event_dy()/2.0;
            if (newValue > sliderXZoom.maximum()) newValue = sliderXZoom.maximum();
            if (newValue < sliderXZoom.minimum()) newValue = sliderXZoom.minimum();
            sliderXZoom.value(newValue);
*/
            //setupGlWindow();
            //glWindow.rightCamera = (int)(sliderXScroll.value() + sliderXZoom.value());
            return 1;

   }
   return Fl_Group::handle(event);
}
